from rest_framework import serializers
from django.forms.models import model_to_dict

from api import models
from collections import OrderedDict
from utils.common import config
from django.db.models import Max, F


class MediaModelSerializer(serializers.ModelSerializer):
    """嵌套的图片序列化器"""

    class Meta:
        model = models.Media
        fields = ['path', 'key']


class ReleaseModelSerializer(serializers.ModelSerializer):
    """发布保存序列化器"""
    """
    {
    "position": "xx",
    "content": "xx",
    "topic": 1,
    "cover": "xx",
    "imageList": [
        {
            "path": "xx",
            "key": "xx"
        },
        {
            "path": "xx",
            "key": "xx"
        }
    ]
}
    """

    imageList = MediaModelSerializer(many=True, write_only=True)

    class Meta:
        model = models.Release
        fields = ['position', 'content', 'topic', 'imageList', 'cover']

    def validate(self, attrs):
        """校验数据"""
        # 校验数据
        # print(attrs.get('imageList'))
        # print(self.context['request'].data)
        self._is_legitimate(attrs)
        return attrs

    def _is_legitimate(self, attrs):
        """进行校验"""
        position = attrs.get('position')
        user_obj = self.context['request'].user
        content = attrs.get('content')
        topic_obj = attrs.get('topic')
        if not position:
            raise serializers.ValidationError('必须选择一个区域哦')
        if not user_obj:
            raise serializers.ValidationError('请先登录哦')
        if not content:
            raise serializers.ValidationError('内容不能为空哦')
        if not topic_obj:
            raise serializers.ValidationError('必须选一个话题哦')
        return position, user_obj, content, topic_obj

    def create(self, validated_data):
        """创建"""
        # pop数据库没有字段
        # print("validated_data", validated_data)
        imageList = validated_data.pop('imageList')
        # print('imageList', imageList)
        # 保存release
        release_obj = self._save_release(validated_data)
        # 保存Media
        self._save_media(release_obj, imageList)
        # 添加话题人数
        self._add_topic_num(release_obj)
        # 给该话题增加对应的热度
        self._add_hot_topic(release_obj)
        return release_obj

    def _save_release(self, validated_data):
        """保存release"""
        release_obj = models.Release.objects.create(
            **validated_data,
            userinfo=self.context['request'].user
        )
        return release_obj

    def _save_media(self, release_obj, imageList):
        """保存图片"""
        media_obj = [models.Media(release=release_obj, **media_item) for media_item in imageList]
        models.Media.objects.bulk_create(media_obj)

    def _add_topic_num(self, release_obj):
        """话题人数加一"""
        topic = models.Topic.objects.filter(id=release_obj.topic.id).first()
        if not topic:
            raise serializers.ValidationError('无当前话题')
        topic.follow_num += 1
        topic.save()

    def _add_hot_topic(self, release_obj):
        # 进行对应话题热度热度增加
        # 取出当前的topic
        topic_id = release_obj.topic.id
        # print(topic_id)
        models.Topic.objects.filter(id=topic_id).update(hot=F('hot') * config.HOT_SELECT)


class TopicModelSerializer(serializers.ModelSerializer):
    """话题序列化器"""

    class Meta:
        model = models.Topic
        fields = ['id', 'name', 'follow_num']


class IndexModelSerializer(serializers.ModelSerializer):
    """index序列化器"""
    update_time = serializers.DateTimeField(format='%Y-%m-%d %H:%M:%S')
    create_time = serializers.DateTimeField(format='%Y-%m-%d %H:%M:%S')
    userinfo = serializers.SerializerMethodField()
    topic = serializers.SerializerMethodField()

    class Meta:
        model = models.Release
        # fields = '__all__'
        fields = ['id', 'update_time', 'update_time', 'create_time', 'position', 'cover', 'thumbs_up', 'watch_num',
                  'comment_num', 'userinfo', 'topic']

    def get_userinfo(self, obj):
        """构造用户数据"""
        userinfo_dic = model_to_dict(instance=obj.userinfo, fields=['id', 'username', 'avatar'])
        return userinfo_dic

    def get_topic(self, obj):
        """构造用户数据"""
        topic_dic = model_to_dict(instance=obj.topic, fields=['id', 'name', 'follow_num'])
        return topic_dic


class IndexDetailsModelSerializer(serializers.ModelSerializer):
    """首页详情序列化器"""
    create_time = serializers.DateTimeField(format='%Y-%m-%d %H:%M:%S')
    userinfo = serializers.SerializerMethodField()
    topic = serializers.SerializerMethodField()
    # cos存储的图片url
    cos_url = serializers.SerializerMethodField()
    # 浏览者的记录
    watch_people = serializers.SerializerMethodField()
    # 一级和二级评论
    comment = serializers.SerializerMethodField()
    # 是否给当前文章点过赞
    is_thumbs_up = serializers.SerializerMethodField()
    # 是否点过关注
    is_follow = serializers.SerializerMethodField()

    # 是否给评论点过赞
    # is_comment_up = serializers.SerializerMethodField()

    class Meta:
        model = models.Release
        fields = ['id', 'create_time', 'position', 'content', 'thumbs_up', 'watch_num', 'is_thumbs_up',
                  'is_follow', 'comment_num', 'userinfo', 'topic', 'cos_url', 'watch_people', 'comment']

    def get_userinfo(self, obj):
        """返回发布者用户数据自定义"""
        release_user = model_to_dict(instance=obj.userinfo, fields=['id', 'username', 'avatar'])
        return release_user

    def get_topic(self, obj):
        """返回当前动态,参加的topic数据自定义"""
        topic_dict = model_to_dict(instance=obj.topic, fields=['id', 'name', 'follow_num'])
        return topic_dict

    def get_cos_url(self, obj):
        """返回当前动态的cos中的图片path"""
        media_query = models.Media.objects.filter(is_show=True, is_delete=False, release=obj)
        # print(media_query)
        media_dic = [model_to_dict(instance=item, fields=['id', 'path']) for item in media_query]
        return media_dic

    def get_watch_people(self, obj):
        """返回此动态的自定义格式"""
        # 默认查询前10条
        watch_num_query = models.WatchNum.objects.filter(is_delete=False, is_show=True, release=obj).order_by('-id')[
                          config.START:config.END]
        # 获取所有的watch_obj
        # watch_obj_list = [watch_obj.userinfo for watch_obj in watch_num_query]

        watch_userinfo_dic = [model_to_dict(instance=item, fields=['id', 'username', 'avatar']) for item in
                              [watch_obj.userinfo for watch_obj in watch_num_query]]
        return watch_userinfo_dic

    def get_comment(self, obj):
        """当前动态的一级和二级自定义返回数据"""
        # 取当前文章所有一级评论--->取所有一级id--->通过reply_id进行分组,获取所有一级id下的最大的二级id--->通过二级id查询二级评论--->一级二级进行合并(进行父子关系构造)
        # 一级评论
        first_comment = models.Comment.objects.filter(is_delete=False, is_show=True, depth=1, release=obj) \
            .values('id',
                    'comment',
                    'depth',
                    'create_time',
                    'thumbs_up',
                    'userinfo__username',
                    'userinfo__avatar',
                    'root'
                    ).order_by('-hot', '-thumbs_up', '-id')  # 先以-comment_up排序,对于一样的,在用-id排
        # 获取所有一级的的id
        first_id = [item['id'] for item in
                    models.Comment.objects.filter(is_show=True, is_delete=False, depth=1, release=obj).values('id')]

        # print("first_id", first_id)
        # first_id [1, 2, 3]
        # 所有一级下面的最大的哪个二级id
        # models.Comment.objects.filter(is_delete=False, is_show=True, depth=2, reply_id__in=first_id).values('reply_id').annotate(max_id=Max('id'))
        # <QuerySet [{'reply_id': 1, 'max_id': 5}, {'reply_id': 2, 'max_id': 7}, {'reply_id': 3, 'max_id': 8}]>
        two_id = [id_query_dic['max_id'] for id_query_dic in
                  models.Comment.objects.filter(is_delete=False, is_show=True, depth=2, release=obj,
                                                reply_id__in=first_id).values('reply_id').annotate(
                      max_id=Max('id'))]

        # 最新的二级评论(通过分组,以reply_id进行分组,)
        # print("two_id", two_id)
        # two_id [5, 7, 8]
        two_comment = models.Comment.objects.filter(id__in=two_id).values('id',
                                                                          'comment',
                                                                          'depth',
                                                                          'create_time',
                                                                          'thumbs_up',
                                                                          # 根id root
                                                                          'root',
                                                                          # 回复的id
                                                                          'reply_id',
                                                                          # 回复者id
                                                                          'reply__userinfo_id',
                                                                          # 回复者名字
                                                                          'reply__userinfo__username',
                                                                          # 回复者头像
                                                                          'reply__userinfo__avatar',
                                                                          )
        # 父子关系的构建
        # 1. 对一级进行数据构造
        # first_dict = OrderedDict()
        first_two_dict = {}
        for item in first_comment:
            item['children'] = []
            item['create_time'] = item['create_time'].strftime('%Y-%m-%d %H:%M:%S')
            first_two_dict[item['id']] = item
        # 2. 对二级进行数据构造
        # 循环二级评论 用replay_id，去初始化的字典里面，找到对应的父级，添加到children里面
        for node in two_comment:
            reply_id = node['reply_id']
            if reply_id in first_two_dict:
                node['create_time'] = node['create_time'].strftime('%Y-%m-%d %H:%M:%S')
                # first_two_dict[reply_id]['children'] = [node]  %H:%M:%S
                first_two_dict[reply_id]['children'].append(node)
        return first_two_dict.values()

    def get_is_thumbs_up(self, obj):
        """是否给文章点过赞"""
        exist = models.ThumbsUp.objects.filter(is_delete=False, is_show=True, userinfo=self.context['request'].user,
                                               release=obj).exists()
        return exist

    def get_is_follow(self, obj):
        """是否点过关注"""
        # 当前登录用户，是否关注过，当前动态的发布者
        current_user = self.context['request'].user
        if current_user == obj.userinfo:
            return
        exist = models.Follow.objects.filter(oneself=current_user, follow=obj.userinfo, is_delete=False,
                                             is_show=True).exists()
        return exist

    # def get_is_comment_up(self, obj):
    #     """是否给评论点过赞"""
    #     # 找到当前评论的id
    #     models.CommentUp.objects.filter(is_delete=False, is_show=True, userinfo=self.context['request'].user,
    #                                     comment='')


class CommentModelSerializer(serializers.ModelSerializer):
    """获取更多评论&&保存评论序列化器"""
    userinfo__username = serializers.CharField(source='userinfo.username')
    userinfo__avatar = serializers.CharField(source='userinfo.avatar')
    create_time = serializers.DateTimeField(format='%Y-%m-%d %H:%M:%S')
    reply__userinfo_id = serializers.CharField(source='reply.userinfo_id')
    reply__userinfo__username = serializers.CharField(source='reply.userinfo.username')
    reply__userinfo__avatar = serializers.CharField(source='reply.userinfo.avatar')

    class Meta:
        model = models.Comment
        fields = ['id', 'comment', 'depth', 'create_time', 'thumbs_up', 'reply_id', 'reply__userinfo_id',
                  'reply__userinfo__username', 'reply__userinfo__avatar', 'userinfo__username', 'userinfo__avatar',
                  'root']


class PostCommentModelSerializer(serializers.ModelSerializer):
    """评论提交"""
    """
    # 一级
    {
    "comment": "一级评论测试",
    "release": 31,
    "reply": null,
    "root": null,
    "depth": 1
}
# 二级及三级...评论
{
    "comment": "一级评论测试",
    "release": 31,
    "reply": 29,
    "root": 2,
    "depth": 2
}
    # 提交的数据
    comment/release/reply/root/depth
    """
    # 当前评论者的数据
    userinfo__username = serializers.CharField(source='userinfo.username', read_only=True)
    userinfo__avatar = serializers.CharField(source='userinfo.avatar', read_only=True)
    create_time = serializers.DateTimeField(format='%Y-%m-%d %H:%M:%S', read_only=True)
    # 被回复者的消息
    reply__userinfo_id = serializers.CharField(source='reply.userinfo.id', read_only=True)
    reply__userinfo__username = serializers.CharField(source='reply.userinfo.username', read_only=True)
    reply__userinfo__avatar = serializers.CharField(source='reply.userinfo.avatar', read_only=True)
    thumbs_up = serializers.CharField(read_only=True)

    class Meta:
        model = models.Comment
        fields = ['id', 'comment', 'depth',
                  'create_time', 'thumbs_up', 'reply_id', 'reply__userinfo_id', 'reply__userinfo__username',
                  'reply__userinfo__avatar', 'userinfo__username', 'userinfo__avatar',
                  'release', 'reply', 'root']


class FanDetailModelSerializer(serializers.ModelSerializer):
    """粉丝详细序列化器"""
    fan = serializers.SerializerMethodField()
    create_time = serializers.DateTimeField(format='%Y-%m-%d %H:%M:%S', read_only=True)

    class Meta:
        model = models.Follow
        fields = ['fan', 'create_time']

    def get_fan(self, obj):
        """获取粉丝详细数据"""
        fan_info = model_to_dict(instance=obj.fan, fields=['id', 'username', 'avatar'])
        return fan_info


class FollowDetailModelSerializer(serializers.ModelSerializer):
    """粉丝详细序列化器"""
    follow = serializers.SerializerMethodField()
    create_time = serializers.DateTimeField(format='%Y-%m-%d %H:%M:%S', read_only=True)

    class Meta:
        model = models.Follow
        fields = ['follow', 'create_time']

    def get_follow(self, obj):
        """获取粉丝详细数据"""
        follow_info = model_to_dict(instance=obj.follow, fields=['id', 'username', 'avatar'])
        return follow_info
